#include<pthread.h>
#include <string>
#include <cstdlib>
#include <cstring>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
//#include"Daemon.hpp"
#include"threadpool.hpp"
#include"Task.hpp"

std::string defaultip = "0.0.0.0";
const int backlog = 10;



class Tcpserver;

struct Client
{
    Tcpserver* tcpserver;
    int sockfd_;
    string clientip_;
    uint16_t clientport_;
};

enum
{
    UsageError = 1,
    SocketError,
    BindError,
    ListenError
};

class Tcpserver
{
public:
   
    Tcpserver(const uint16_t port, const std::string &ip = defaultip)
        : port_(port), ip_(ip)
    {
    }
    void InitServer()
    {
        
        //socket->setsockopt>bind->listen->sockfd(read,write)
        listensock_ = socket(AF_INET, SOCK_STREAM, 0);
        if (listensock_ < 0)
        {
            lg(Fatal, "create socket, errno: %d, errstring: %s", errno, strerror(errno));
            exit(SocketError);
        }
        lg(Info, "create socket success, listensock_: %d", listensock_);

        int opt = 1;
        setsockopt(listensock_, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt));

        struct sockaddr_in local;
        bzero(&local, sizeof(local));
        local.sin_port = htons(port_);
        local.sin_family = AF_INET;
        inet_aton(ip_.c_str(), &(local.sin_addr));
        socklen_t len = sizeof(local);
        if (bind(listensock_, (sockaddr *)&(local), len) < 0)
        {
            lg(Fatal, "bind error, errno: %d, errstring: %s", errno, strerror(errno));
            exit(BindError);
        }
        // Tcp是面向连接的，服务器一般是比较“被动的”，服务器一直处于一种，一直在等待连接到来的状态
        // backlog是设置多少个客户端进入连接等待，如果多于这个连接数，那么其他还要进入连接的客户端就进入等待
        if (listen(listensock_, backlog) < 0)
        {
            lg(Fatal, "listen error, errno: %d, errstring: %s", errno, strerror(errno));
            exit(ListenError);
        }
        lg(Info, "listen socket success, listensock_: %d", listensock_);
    }
    
   static  void * routine(void *args)
    {
        Client* cdata=static_cast<Client*>(args);
        cdata->tcpserver->Server(cdata->sockfd_,cdata->clientip_,cdata->clientport_);
        return nullptr;
    }

    void Server(int sockfd,string clientip,uint16_t clientport)
    {
        char buffer[4096];
        while(true){
            ssize_t n=read(sockfd,buffer,sizeof(buffer));
            if(n>0)
            {
                buffer[n]=0;
                cout<<"client say#"<<buffer<<endl;
                string echo_string="tcpserver echo#";
                echo_string+=buffer;
                write(sockfd,echo_string.c_str(),echo_string.size());
            }
            else if(n==0)
            {
                lg(Info, "%s:%d quit, server close sockfd: %d", clientip.c_str(), clientport, sockfd);
                break;
            }
            else{
                lg(Warning, "read error, sockfd: %d, client ip: %s, client port: %d", sockfd, clientip.c_str(), clientport);
                break;
            }
        }
    }

    void start()
    {
        daemon(1,0);
        //Daemon("./");
        for (;;)
        {
            lg(Info, "tcpServer is running....");
            struct sockaddr_in client;
            bzero(&client, sizeof(client)); //
            socklen_t len = sizeof(client);
            int sockfd = accept(listensock_, (sockaddr *)&client, &len); // 接收
            if (sockfd < 0)
            {
                continue;
            }
            uint16_t clientport=ntohs(client.sin_port);
            char bufferip[1024];
            inet_ntop(AF_INET,&(client.sin_addr),bufferip,sizeof(bufferip));
            lg(Info, "get a new link..., sockfd: %d, client ip: %s, client port: %d", sockfd, bufferip, clientport);
            
            //单进程版（问题：只会给一个服务器提供服务，一直卡死在一个里面）
            // Server(sockfd,buffer,clientport);
            // close(sockfd);
            
            // //多进程版
            //多进程版通过创建孙子进程来创建独立的进程去处理，不使用子进程，因为父进程不会退出，子进程无法成为独立进程。
            // pid_t pid=fork();
            // if(pid==0)//子进程
            // {
            //     cout<<"fork success"<<endl;
            //     close(listensock_);//子进程关闭了listensock_
            //     if(fork()>0)//子进程退出,子进程退出时sockfd也会退出
            //     {
            //         exit(0);
            //     }
            //     //孙子进程变为孤儿进程,归为系统
            //     Server(sockfd,bufferip,clientport);
            //     close(sockfd);
            //     exit(0);
            // }
            // close(sockfd);
            // //父进程
            // pid_t rid=waitpid(pid,nullptr,0);
            // (void)rid;//相当于assert
        
            //多线程版
            // pthread_t tid;
            // Client *data=new Client();
            // data->clientip_=bufferip;
            // data->clientport_=clientport;
            // data->sockfd_=sockfd;
            // data->tcpserver=this;
            // pthread_create(&tid,nullptr,routine,data);

            //线程池版本
            Task t(sockfd,bufferip,clientport);
            Threadpool<Task>::GetInstance()->start();
            Threadpool<Task>::GetInstance()->push(t);
        }
    }
    ~Tcpserver()
    {}
private:
    int listensock_;
    uint16_t port_;
    std::string ip_;
};
